package util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.Hashtable;

import com.mysql.jdbc.Connection;
import com.mysql.jdbc.PreparedStatement;

public class PageRank {

	public static final String url = "jdbc:mysql://127.0.0.1/SearchEngine?useUnicode=true&characterEncoding=UTF-8";
	public static final String name = "com.mysql.jdbc.Driver";
	public static final String user = "root";
	public static final String password = "33505832";

	public static void main(String[] args) throws Exception {

		String[] linesarr;
		Hashtable<String, Integer> docIDandNum = new Hashtable<String, Integer>();
		int total = 0;
		int father, son;
		int outdegree = 0;
		Connection conn = null;
		PreparedStatement pst = null;
		ResultSet rs = null;
		Class.forName(name);
		// 指定连接类型
		conn = (Connection) DriverManager.getConnection(url, user, password);// 获取连接
		// 得到docid，计算链接总数total，outdegree在迭代的时候计算

		String sql = "select * from pages";
		pst = (PreparedStatement) conn.prepareStatement(sql);// 准备执行语句
		rs = pst.executeQuery();
		File linkfile = new File("linkmaptest.txt");
		BufferedReader linkinput = new BufferedReader(new FileReader(linkfile));
		String line = linkinput.readLine();
		while (line != null) {
			++total;
			linesarr = line.split(" ");
			if (linesarr.length > 0) {
				if (linesarr[0] != null) {
					docIDandNum.put(linesarr[0], total);
				}
			}
			linesarr = null;
			line = linkinput.readLine();
		}
		linkinput.close();

		if (total > 0) {
			// pageRank[]存放PR值
			float[] pageRank = new float[total + 1];

			// 链入页面的计算总和
			float[] prTmp = new float[total + 1];

			// 设置pageRank[]初始值为1.0f
			for (int i = 1; i <= total; ++i) {
				pageRank[i] = 1.0f;
				prTmp[i] = 0.0f;
			}

			// 当前页面的PR值
			float fatherRank = 1f;

			// 阻尼系数d或称为alpha
			float alpha = 0.85f;

			// 进行10次迭代
			for (int iterator = 0; iterator < 10; iterator++) {
				long startTime = System.currentTimeMillis();

				linkinput = new BufferedReader(new FileReader(linkfile));
				line = linkinput.readLine();
				// 读出docid和outdegree和sons
				while (line != null) {
					linesarr = line.split(" ");
					if (linesarr.length > 0) {
						outdegree = linesarr.length - 1;
						for (int j = 1; j <= linesarr.length - 1; ++j) {
							// 指向自身的链接无效，不计算在内
							if (linesarr[j].equals(linesarr[0]))
								outdegree--;
						}
					}
					if (outdegree > 0) {
						father = (int) docIDandNum.get(linesarr[0]);
						// 对应公式中的pr(Ti)/c(Ti),Ti为指向father的页面
						fatherRank = pageRank[father] / outdegree;
						for (int k = 1; k <= linesarr.length - 1; ++k) {
							if (linesarr[k].equals(linesarr[0])) {
								continue;
							}
							son = docIDandNum.get(linesarr[k]);
							if (total >= son && son >= 0) {
								prTmp[son] += fatherRank;
							}
						}
					}
					linesarr = null;
					line = linkinput.readLine();
				}

				// 准备下次迭代的初始值
				for (int i = 1; i <= total; ++i) {
					// PR公式1
					// prTmp[i] = 0.15f + alpha * prTmp[i];

					// PR公式2
					prTmp[i] = 0.15f / total + alpha * prTmp[i];

					// 每次迭代后的真正pr值
					pageRank[i] = prTmp[i];

					prTmp[i] = 0.0f;
				}
				linkinput.close();

				long endTime = System.currentTimeMillis();
				System.out.println("第" + iterator + "次迭代耗时" + (endTime - startTime) + "ms");
			}

			// 获取字段
			for (int i = 1; i <= total; ++i) {
				String sqlI = "INSERT INTO pagerank (id,page_rank) VALUES (\"" + "1" + "\",\" "
						+ String.valueOf(pageRank[i]);
				pst = (PreparedStatement) conn.prepareStatement(sqlI);// 准备执行语句
				pst.execute();
			}
			conn.close();
			pst.close();
		}
	}
}
